
package cn.edu.tsinghua.hpc.gsmsensor;

import cn.edu.tsinghua.hpc.gsmtest.db.GSMDBAdapter;
import cn.edu.tsinghua.hpc.gsmtest.db.TrackStorageDBAdapter;
import cn.edu.tsinghua.hpc.gsmtest.utils.LocationUtils;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.location.LocationListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ResourceCursorAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.AdapterView.OnItemSelectedListener;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Timestamp;
import java.util.Timer;
import java.util.TimerTask;

public class StationInfo extends Activity {
    private static final String TAG = "StationInfo";

    private Cursor mCursor;

    private ResourceCursorAdapter adapter;

    static final int MENU_IMPORT_DATA = 0;

    static final int MENU_WIPE_DATA = 1;

    static final int MENU_EXPORT_DATA = 2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.station_info);

        initSpinner();
        initButton();

        dialogShowHandler = new DialogShowHandler(new AlertDialog.Builder(StationInfo.this)
                .setTitle(R.string.menu_import_data).setPositiveButton(android.R.string.ok, null)
                .setMessage(R.string.import_end));
        showCurrentPosition();

        onResume();
    }

    @Override
    protected void onResume() {
        super.onResume();
        showCurrentPosition();
    }

    private void initButton() {
        Button map = (Button) this.findViewById(R.id.map_view_button);
        map.setOnClickListener(mMapListener);
        Button pos = (Button) this.findViewById(R.id.detail_pos_button);
        pos.setOnClickListener(mPositionListener);
        Button cur = (Button) this.findViewById(R.id.show_current_position_button);
        cur.setOnClickListener(mCurrentPositionListener);
        ToggleButton save = (ToggleButton) this.findViewById(R.id.save_tracker_button);
        save.setOnCheckedChangeListener(mRunListener);
    }

    private void showCurrentPosition() {
        GsmCellLocation loc = LocationUtils.getInstance(StationInfo.this).getCellLocation();
        ((EditText) StationInfo.this.findViewById(R.id.lac_et)).setText(String
                .valueOf(loc.getLac()));
        ((EditText) StationInfo.this.findViewById(R.id.cid_et)).setText(String
                .valueOf(loc.getCid()));
        ((EditText) StationInfo.this.findViewById(R.id.lat_et)).setText("");
        ((EditText) StationInfo.this.findViewById(R.id.lon_et)).setText("");
    }

    OnClickListener mMapListener = new OnClickListener() {
        public void onClick(View v) {
            Intent intent = new Intent();
            double lat = 0.0, lon = 0.0;
            try {
                lat = Double.valueOf(((EditText) StationInfo.this.findViewById(R.id.lat_et))
                        .getText().toString());
                lon = Double.valueOf(((EditText) StationInfo.this.findViewById(R.id.lon_et))
                        .getText().toString());
            } catch (Exception e) {

            }
            intent.putExtra("lat", lat);
            intent.putExtra("lon", lon);
            intent.setClass(StationInfo.this, MyMapView.class);
            startActivity(intent);

        }
    };

    private class QueryLocationThread extends Thread {
        private String lac, cid;

        public QueryLocationThread(String lac, String cid) {
            this.lac = lac;
            this.cid = cid;
        }

        @Override
        public void run() {
            final Location loc = LocationUtils.getInstance(StationInfo.this).getLocationFromCid(
                    Integer.parseInt(lac), Integer.parseInt(cid));
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    if (loc != null) {
                        ((EditText) StationInfo.this.findViewById(R.id.lat_et)).setText(String
                                .valueOf(loc.getLatitude()));
                        ((EditText) StationInfo.this.findViewById(R.id.lon_et)).setText(String
                                .valueOf(loc.getLongitude()));
                    }

                }
            });

            dialogShowHandler.sendEmptyMessage(1);

        }
    }

    OnClickListener mPositionListener = new OnClickListener() {
        public void onClick(View v) {
            String lac = ((EditText) StationInfo.this.findViewById(R.id.lac_et)).getText()
                    .toString();
            String cid = ((EditText) StationInfo.this.findViewById(R.id.cid_et)).getText()
                    .toString();
            showDialog(0);
            new QueryLocationThread(lac, cid).start();

        }
    };

    OnClickListener mCurrentPositionListener = new OnClickListener() {
        public void onClick(View v) {
            showCurrentPosition();

        }
    };

    private void refreshStationList() {
        if (mCursor != null) {
            mCursor.close();
        }
        GSMDBAdapter db = new GSMDBAdapter(StationInfo.this).open();
        mCursor = db.getAllData();
        startManagingCursor(mCursor);
        adapter.changeCursor(mCursor);
    }

    private void initSpinner() {
        Spinner s1 = (Spinner) findViewById(R.id.station_spinner);

        GSMDBAdapter db = new GSMDBAdapter(StationInfo.this).open();
        mCursor = db.getAllData();
        startManagingCursor(mCursor);
        adapter = new ResourceCursorAdapter(this, android.R.layout.simple_spinner_item, mCursor,
                true) {

            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                if (cursor != null && view != null) {
                    ((TextView) view).setText(mCursor.getString(mCursor.getColumnIndex("lac"))
                            + " " + mCursor.getString(mCursor.getColumnIndex("cid")));
                }

            }
        };

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        s1.setAdapter(adapter);
        s1.setOnItemSelectedListener(new OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (mCursor != null) {
                    mCursor.moveToPosition(position);

                    ((EditText) StationInfo.this.findViewById(R.id.lac_et)).setText(mCursor
                            .getString(mCursor.getColumnIndex("lac")));
                    ((EditText) StationInfo.this.findViewById(R.id.cid_et)).setText(mCursor
                            .getString(mCursor.getColumnIndex("cid")));
                    ((EditText) StationInfo.this.findViewById(R.id.lat_et)).setText(mCursor
                            .getString(mCursor.getColumnIndex("lat")));
                    ((EditText) StationInfo.this.findViewById(R.id.lon_et)).setText(mCursor
                            .getString(mCursor.getColumnIndex("lon")));
                }
            }

            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

    }

    private class DialogShowHandler extends Handler {
        AlertDialog.Builder builder;

        public DialogShowHandler(AlertDialog.Builder builder) {
            this.builder = builder;
        }

        @Override
        public void handleMessage(Message msg) {
            StationInfo.this.dismissDialog(0);
            switch (msg.what) {
                case 0:
                    builder.show();
                    refreshStationList();
                    break;
                case 1:
                    break;
            }

        }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case 0: {
                ProgressDialog dialog = new ProgressDialog(this);
                dialog.setMessage(getString(R.string.waiting));
                dialog.setIndeterminate(true);
                dialog.setCancelable(false);
                return dialog;
            }
            default:
                break;
        }
        return null;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.clear();
        menu.add(0, MENU_IMPORT_DATA, 0, R.string.menu_import_data).setIcon(
                R.drawable.ic_menu_import);
        menu.add(0, MENU_WIPE_DATA, 1, R.string.menu_wipe_data).setIcon(
                android.R.drawable.ic_menu_delete);
        menu.add(0, MENU_EXPORT_DATA, 2, R.string.menu_export_track_data).setIcon(
                R.drawable.ic_menu_import_export);
        return true;
    }

    private class ImportDataThread extends Thread {
        private String name;

        public ImportDataThread(String fileName) {
            name = fileName;
        }

        @Override
        public void run() {
            GSMDBAdapter db = new GSMDBAdapter(StationInfo.this).open();
            try {
                BufferedReader br = new BufferedReader(new FileReader("/sdcard/" + name));
                String line = null;

                while ((line = br.readLine()) != null) {
                    String[] data = line.split(" |\t");
                    if (data.length == 4) {
                        db.insertData(data[0], data[1], data[2], data[3]);
                    }
                }

                dialogShowHandler.sendEmptyMessage(0);
            } catch (FileNotFoundException e) {

            } catch (IOException e) {

            } finally {
                db.close();
            }

        }
    }

    private class StoreLocaitionRunnable implements Runnable {
        private String lac, cid;

        private long currentTime;

        public StoreLocaitionRunnable(String lac, String cid, long currentTime) {
            this.lac = lac;
            this.cid = cid;
            this.currentTime = currentTime;
        }

        @Override
        public void run() {
            Location loc = LocationUtils.getInstance(StationInfo.this).getCurrentLocation();
            if (loc != null) {
                TrackStorageDBAdapter db = new TrackStorageDBAdapter(StationInfo.this).open();
                db.insertData(lac, cid, String.valueOf(loc.getLatitude()), String.valueOf(loc
                        .getLongitude()), currentTime);
                db.close();
            }

        }
    }

    private class StoreLocationTask extends TimerTask {

        @Override
        public void run() {
            Location loc = LocationUtils.getInstance(StationInfo.this).getCurrentMachineLocation();
            GsmCellLocation cell = LocationUtils.getInstance(StationInfo.this).getCellLocation();
            if (cell != null) {
                if (loc != null) {
                    TrackStorageDBAdapter db = new TrackStorageDBAdapter(StationInfo.this).open();
                    db.insertData(String.valueOf(cell.getLac()), String.valueOf(cell.getCid()),
                            String.valueOf(loc.getLatitude()), String.valueOf(loc.getLongitude()),
                            System.currentTimeMillis());
                    db.close();
                } else {
                    new Thread(new StoreLocaitionRunnable(String.valueOf(cell.getLac()), String
                            .valueOf(cell.getCid()), System.currentTimeMillis())).start();
                }
            }

        }
    }

    private Timer mTimer = new Timer();

    private LocationListener listener = new LocationListener() {

        @Override
        public void onLocationChanged(Location location) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO Auto-generated method stub

        }

    };

    private CompoundButton.OnCheckedChangeListener mRunListener = new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                EditText internal = (EditText) findViewById(R.id.save_internal);
                LocationUtils.getInstance(StationInfo.this).forceLocationManagerUpdate(listener);
                if (internal.getText() != null && !internal.getText().toString().equals("")) {
                    mTimer = new Timer();
                    new Timer().scheduleAtFixedRate(new StoreLocationTask(), 0, Integer
                            .parseInt(internal.getText().toString()) * 1000);
                }

            } else {
                LocationUtils.getInstance(StationInfo.this)
                        .forceLocationManagerStopUpdate(listener);
                mTimer.cancel();

            }

        }

    };

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        ((EditText) findViewById(R.id.save_internal)).setText(savedInstanceState
                .getCharSequence("save_internal"));
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putString("save_internal", ((EditText) findViewById(R.id.save_internal)).getText()
                .toString());

    }

    private DialogShowHandler dialogShowHandler;

    private void doImportFromSdCard() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // SDcard mounted
            File sdDir = Environment.getExternalStorageDirectory();
            if (sdDir.canRead()) {
                final String[] names = sdDir.list(new FilenameFilter() {

                    @Override
                    public boolean accept(File dir, String filename) {
                        String[] arrName = filename.split("\\.");
                        if (arrName.length == 2 && arrName[1].equalsIgnoreCase("txt")) {
                            return true;
                        }
                        return false;
                    }
                });
                final DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();

                        final String fileName = names[which];
                        Log.d(TAG, "Select file " + fileName);
                        showDialog(0);
                        new ImportDataThread(fileName).start();
                    }
                };

                new AlertDialog.Builder(this).setTitle(R.string.menu_import_data)
                        .setNegativeButton(android.R.string.cancel, null).setSingleChoiceItems(
                                names, -1, clickListener).show();
            } else {
            }
        }
    }

    private class ExportAsyncTask extends AsyncTask<Cursor, Integer, Boolean> {

        private ProgressDialog dialog;

        @Override
        protected Boolean doInBackground(Cursor... arg0) {
            Cursor c = arg0[0];
            int count = 0;
            if (c != null && c.moveToFirst()) {
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    File d = new File("/mnt/sdcard/gsmtest/");
                    if (!d.exists()) {
                        d.mkdir();
                    }
                } else {
                    return Boolean.FALSE;
                }
                File text = new File("/mnt/sdcard/gsmtest/trackinfo.txt");
                if(!text.exists()) {
                    try {
                        text.createNewFile();
                    } catch (IOException e) {
                        return Boolean.FALSE;
                    }
                }
                PrintWriter p = null;
                try {
                    p = new PrintWriter(text);
                } catch (FileNotFoundException e) {
                    return Boolean.FALSE;
                }

                if (p != null) {
                    do {
                        p.print(c.getString(c.getColumnIndex("lac")) + " "
                                + c.getString(c.getColumnIndex("cid")) + " "
                                + c.getString(c.getColumnIndex("lat")) + " "
                                + c.getString(c.getColumnIndex("lon")) + " "
                                + new Timestamp(c.getLong(c.getColumnIndex("time"))).toLocaleString()+"\r\n");
                        count++;
                        this
                                .publishProgress((int) ((((float) count / (float) c.getCount())) * 100));
                    } while (c.moveToNext());
                }
                p.close();
                c.close();
            }

            return Boolean.TRUE;
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            dialog.setProgress(progress[0]);
        }

        @Override
        protected void onPostExecute(Boolean result) {
            dialog.dismiss();
            if (!result) {
                Toast.makeText(StationInfo.this, R.string.export_track_data_error,
                        Toast.LENGTH_LONG).show();
            }else{
                Toast.makeText(StationInfo.this, R.string.export_track_data_success,
                        Toast.LENGTH_LONG).show();
            }
        }

        protected void onPreExecute() {
            dialog = new ProgressDialog(StationInfo.this);
            dialog.setTitle(R.string.menu_export_track_data);
            dialog.setCancelable(false);
            dialog.setMax(100);
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.show();
        }

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case MENU_IMPORT_DATA:
                doImportFromSdCard();
                break;
            case MENU_WIPE_DATA: {
                GSMDBAdapter db = new GSMDBAdapter(StationInfo.this).open();
                db.deleteAllData();
                refreshStationList();
                db.close();
                break;
            }
            case MENU_EXPORT_DATA: {
                TrackStorageDBAdapter db = new TrackStorageDBAdapter(StationInfo.this).open();
                new ExportAsyncTask().execute(db.getAllData());
                break;
            }
            default:
                return false;
        }
        return true;
    }
}
